//
//  FormModelProtocol.swift
//  CooperSwift_Example
//
//  Created by 计海峰 on 2021/6/4.
//  Copyright © 2021 CocoaPods. All rights reserved.
//

import Foundation


// MARK: - 动态绑定key
private struct AssociateKeys {
    // 提交数据
    static var dataKey: Void? /// 参数key
    static var showValue: Void? /// 展示的value
    static var keyValue: Void? /// 提交的value
    
    static var additionData: Void? /// 附加参数 会一起提交
    static var hintText: Void? /// 提示文字
    
    static var needKeysHint: Void? /// 需要传的参数 key: hintMessage
    
    static var option: Void? /// 可选参数
    static var doNotSumbit: Void? /// 不需要验证
    
    static var validationBlock: Void? /// 提交验证
    
    static var rules: Void? /// 输入验证
}

//MARK: - 表单每个cell的提交协议
public protocol FormModelProtocol: AssociatedObjectStore { }


public extension FormModelProtocol {
    
    // MARK: - key
    var dataKey: String? {
        get {
            return objc_getAssociatedObject(self, &AssociateKeys.dataKey) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociateKeys.dataKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    
    // MARK: - value 作为显示
    var showValue: String? {
        get {
            return objc_getAssociatedObject(self, &AssociateKeys.showValue) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociateKeys.showValue, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    
    // MARK: - key value
    var keyValue: String? {
        get {
            return associatedObject(forKey: &AssociateKeys.keyValue, default: showValue, ploicy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.keyValue, ploicy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    
    // 提示语
    var hintText: String {
        get {
            return associatedObject(forKey: &AssociateKeys.hintText, default: "请输入", ploicy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.hintText, ploicy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    
    // 可选参数
    var option: Bool {
        get {
            return associatedObject(forKey: &AssociateKeys.option, default: false, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.option, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 不要上传
    var doNotSumbit: Bool {
        get {
            return associatedObject(forKey: &AssociateKeys.doNotSumbit, default: false, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.doNotSumbit, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 附加参数
    var additionData: Dictionary<String, String> {
        get {
            return associatedObject(forKey: &AssociateKeys.additionData, default: [:], ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.additionData, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 需要传的参数 key: hintMessage
    var needKeysHint: Array<[String: String]> {
        get {
            return associatedObject(forKey: &AssociateKeys.needKeysHint, default: [], ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.needKeysHint, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    // 需要自定义验证
    var validationBlock: (() -> (String, String)?)? {
        get {
            return associatedObject(forKey: &AssociateKeys.validationBlock)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.validationBlock, ploicy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    
    // 需要传的参数 key: hintMessage
    var rules: [LimitInputEnum] {
        get {
            return associatedObject(forKey: &AssociateKeys.rules, default: [], ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        set {
            setAssociatedObject(newValue, forKey: &AssociateKeys.rules, ploicy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
}


public extension FormModelProtocol {
    
    // 检查key 和 value
    func checkKeyAndValue() -> (String, String)? {
        /// 自定义验证
        if let block = validationBlock {
            return block()
        }
        /// 通用验证
        guard let key = dataKey, let value = keyValue ?? showValue else {
            return nil
        }
        if key.isEmpty || value.isEmpty {
            return nil
        }
        return (key, value)
    }
    
    // 提交的参数
    func sumbitData() -> [String: Any]? {
        if doNotSumbit { return nil }
        guard let (key, value) = checkKeyAndValue() else {
            return additionData.isEmpty ? nil : additionData
        }
        return additionData.isEmpty ? [key: value] : additionData.add([key: value])
    }
    
    // 是否可以提交
    func isReady() -> Bool {
        if doNotSumbit { return true }
        guard let _ = checkKeyAndValue() else { return false }
        return sumbitData() != nil
    }
    
    // 错误信息
    func errorInfo() -> String {
        if !self.needKeysHint.isEmpty {
            guard let sumbitData = self.sumbitData() else {
                return hintText
            }
            var hint = hintText
            self.needKeysHint.forEach { dict in
                dict.keys.forEach {
                    if !sumbitData.keys.contains($0) {
                        hint = dict[$0] ?? hint
                    }
                }
            }
            return hint
        }
        return hintText
    }
    
}
